//==============================================================================
// GenBankEntry.cc
// ----------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
// $Id: GenBankEntry.cc,v 1.1 2000/01/31 21:13:16 kdurbin Exp $
//------------------------------------------------------------------------------
// $Log: GenBankEntry.cc,v $
// Revision 1.1  2000/01/31 21:13:16  kdurbin
// Initial revision
//
//   
//==============================================================================
//.......1.........2.........3.........4.........5.........6.........7.........8
//

#include "GenBankEntry.hh"


//---------------------------------------------------------------------------
// * Print
//---------------------------------------------------------------------------
// 
void 
FeatureVec::Print(ostream &out)
{
	for(int i =0;i<(*this).size();i++){
		(*this)[i].Print(out);
		cout<<endl;
	}
}

//---------------------------------------------------------------------------
// * InitKeywordList
//---------------------------------------------------------------------------
// 
void
GenBankEntry::InitKeywordList()
{
	int idx=0;
	while(gFeatureNames[idx] != "END"){
		mKeywordList.push_back(gFeatureNames[idx]);
		idx++;
	}
}

//---------------------------------------------------------------------------
// * ParseFeatureLine
//---------------------------------------------------------------------------
// Takes a single line of genbank features and parses them.  Handles 
// the join(...) construct.  Will accep multiple features on a single line 
// as in the FASTA comment line format.   GenBank records often contain 
// join(..) constructs that span several lines.  This method only works
// on one line at a time and relies on the caller to concatenate multiple
// join(..) lines into a single longer line. 
// 
//
void
GenBankEntry::ParseFeatureLine(string &Line,int offset)
{	
	Feature temp;
	string keyword;
	do{
		if (GetNextKeyword(mKeywordList,Line,offset,offset,keyword)){
			temp.mKind = keyword;
			// Check for a join
			int offset2;
			GetNextKeyword(mKeywordList,Line,offset,offset2,keyword);
			if (keyword == "join"){
				int endOfJoin = Line.find(")",offset2);
				do{
					int num1 = GetNextInteger(Line,offset2,offset2);
 					int num2 = GetNextInteger(Line,offset2,offset2);
 					if (offset >=0){
 						temp.mStart = num1;
 						temp.mEnd = num2;
 					}else{
 						cout<<"Format error.\n"<<endl;
 					}
 					// The pieces of a join are saved as individual feature
 					// objects.  The association is noted, however, by the 
 					// joined features sharing a common mJoinIdx.   
 					temp.mJoinID = mJoinIdx;
 					mFeatures.push_back(temp);
				}while((offset2 < endOfJoin) || (offset2 < 0));
				mJoinIdx++;
				offset = offset2;
			}else{
				int num1 = GetNextInteger(Line,offset,offset);
 				int num2 = GetNextInteger(Line,offset,offset);
 				if (offset >=0){
 					temp.mStart = num1;
 					temp.mEnd = num2;
 				}else{
 					cout<<"Format error.\n"<<endl;
 				}
 				temp.mJoinID = 0;	// 0 is idea of non-joined features
 				mFeatures.push_back(temp);
 			}
		}
   }while(offset >=0);	
}
  
//---------------------------------------------------------------------------
// * ParseFASTALine
//---------------------------------------------------------------------------
// As a convenience, sequence features are sometimes recorded in the FASTA
// header as follows:
//
// CABP1 gene; X52688;intron 931..1041,prim_transcript 857..1980,CDS 897..1898";
//
// The names are extracted and the rest of the line passed to the standard
// GenBank line parser. 
//
void
GenBankEntry::ParseFASTALine(string &Line)
{
	// Extract name and accession number
	int sIdx = Line.find(";");
	if (sIdx > -1) mName = Line.substr(0,sIdx-0);	
	
	int sIdx2 = Line.find(";",sIdx+1);
	if (sIdx2 > -1) mAccession = Line.substr(sIdx+1,sIdx2-(sIdx+1));
	
	// Parse the remainder of the line for features.
	ParseFeatureLine(Line,sIdx2+1);
}

//---------------------------------------------------------------------------
// * ParseGenBankFile
//---------------------------------------------------------------------------
// 
bool
GenBankEntry::ParseGenBankFile(const string &FileName)
{
	char buffer[LINE_BUFFER_SIZE];
	string tempLine,tempLine2;
	
	ifstream inFile;
	inFile.open(FileName.c_str(),ios::in);
	if (inFile.fail()){
		cout<<FileName<<" file open failed (Read Multiple FASTA)"<<endl;
		return(false);
	}
	
	// KJD Skip over the header information for now.
	bool bFeatureMarker = false;
	do{
		inFile.getline(buffer,LINE_BUFFER_SIZE);
		tempLine =buffer;
		int idx = tempLine.find("FEATURES");
		bFeatureMarker = (idx>=0);
	}while((!inFile.eof()) && (!bFeatureMarker));
	
	
	// Parse Genbank Features.
  	bool bContinuedJoinLine;

	do{
    inFile.getline(buffer,LINE_BUFFER_SIZE);
    tempLine = buffer;  // make it into a string for find,etc.
    if (tempLine != ""){
    	// If there is a "join" keyword on this line but no closing ")", then the 
    	// line is a continued join line.  In that case, we will concatenate all
    	// of the join lines (all lines until a ")" is encountered) and pass 
    	// a really large single line in to the parser. 
    	int idx1 = tempLine.find("join");
    	int idx2 = tempLine.find(")");
    	bContinuedJoinLine = ((idx1>=0) && (idx2<0));
	  	if (bContinuedJoinLine){
	  		do{
	  			inFile.getline(buffer,LINE_BUFFER_SIZE);
	  			tempLine2 = buffer;
	  			tempLine += tempLine2;
	  			idx2 = tempLine2.find(")");
	  		}while(idx2 < 0);
		}
		// KJD Skip comment lines for now.
		int idx = tempLine.find("/");
		if (idx < 0){
			ParseFeatureLine(tempLine,0);
		}
	}
 }while(!inFile.eof());
 return(true);
}



